home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / MacPerl 5.1.3 / Mac_Perl_513_src / MacPerl5 / MPDrop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-12  |  7.7 KB  |  366 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPDrop.c            -    Droplets
  4. Author    :    Matthias Neeracher
  5. Language    :    MPW C
  6.  
  7. $Log: MPDrop.c,v $
  8. Revision 1.2  1994/05/04  02:50:15  neeri
  9. Debugger support.
  10.  
  11. Revision 1.1  1994/02/27  23:00:19  neeri
  12. Initial revision
  13.  
  14. Revision 0.1  1993/10/02  00:00:00  neeri
  15. Compiles correctly
  16.  
  17. *********************************************************************/
  18.  
  19. #include <Dialogs.h>
  20. #include <QuickDraw.h>
  21. #include <Windows.h>
  22. #include <Menus.h>
  23. #include <Fonts.h>
  24. #include <AppleEvents.h>
  25. #include <AERegistry.h>
  26. #include <Processes.h>
  27. #include <files.h>
  28. #include <StandardFile.h>
  29. #include <Aliases.h>
  30. #include <GestaltEqu.h>
  31. #include <Folders.h>
  32. #include <Errors.h>
  33. #include <Resources.h>
  34. #include <SegLoad.h>
  35.  
  36. #if !defined(powerc) && !defined(__powerc)
  37. #pragma segment Main
  38. #endif
  39.  
  40. #define FAILOSERR(call) if (err = call) return err; else 0
  41.  
  42. Boolean        gQuitting;
  43. FSSpec        gMySelf;
  44. EventRecord    gLastEvent;
  45.  
  46. pascal Boolean CheckEnvironment()
  47. {
  48.     long    result;
  49.     
  50.     if (Gestalt(gestaltAppleEventsAttr, &result))
  51.         return false;
  52.         
  53.     return (result & (1 << gestaltAppleEventsPresent)) != 0;
  54. }  /* CheckEnvironment */
  55.  
  56. /* The following stuff is adapted from Jens Peter Alfke's SignatureToApp code */
  57.  
  58. OSErr MacPerlRunning(ProcessSerialNumber *psn)
  59. {
  60.     OSErr err;
  61.     ProcessInfoRec info;
  62.     
  63.     psn->highLongOfPSN = 0;
  64.     psn->lowLongOfPSN  = kNoProcess;
  65.     do    {
  66.         FAILOSERR(GetNextProcess(psn));
  67.             
  68.         info.processInfoLength     = sizeof(info);
  69.         info.processName             = nil;
  70.         info.processAppSpec         = nil;
  71.         
  72.         FAILOSERR(GetProcessInformation(psn, &info));
  73.     } while(info.processSignature != 'McPL');
  74.  
  75.     *psn = info.processNumber;
  76.     
  77.     return noErr;
  78. }
  79.  
  80. OSErr GetSysVolume(short *vRefNum)
  81. {
  82.     long dir;
  83.     
  84.     return FindFolder(kOnSystemDisk, kSystemFolderType, false, vRefNum, &dir);
  85. }
  86.  
  87. OSErr GetIndVolume(short index, short *vRefNum)
  88. {
  89.     OSErr             err;
  90.     ParamBlockRec     pb;
  91.     
  92.     pb.volumeParam.ioNamePtr     = nil;
  93.     pb.volumeParam.ioVolIndex     = index;
  94.     
  95.     FAILOSERR(PBGetVInfoSync(&pb));
  96.     
  97.     *vRefNum = pb.volumeParam.ioVRefNum;
  98.     
  99.     return noErr;
  100. }
  101.  
  102. OSErr VolHasDesktopDB(short vRefNum, Boolean * hasDesktop)
  103. {
  104.     OSErr                         err;
  105.     HParamBlockRec             pb;
  106.     GetVolParmsInfoBuffer     info;
  107.     
  108.     pb.ioParam.ioNamePtr     = nil;
  109.     pb.ioParam.ioVRefNum     = vRefNum;
  110.     pb.ioParam.ioBuffer         = (Ptr)&info;
  111.     pb.ioParam.ioReqCount     = sizeof(GetVolParmsInfoBuffer);
  112.     
  113.     FAILOSERR(PBHGetVolParmsSync(&pb));
  114.  
  115.     *hasDesktop = (info.vMAttrib & (1 << bHasDesktopMgr))!=0;
  116.     
  117.     return noErr;
  118. }
  119.  
  120. OSErr FindAppOnVolume(short vRefNum, FSSpec *file)
  121. {
  122.     OSErr     err;
  123.     DTPBRec     pb;
  124.     
  125.     /* Get Acess path to Desktop database on this volume */
  126.     
  127.     pb.ioVRefNum         = vRefNum;
  128.     pb.ioNamePtr         = nil;
  129.     FAILOSERR(PBDTGetPath(&pb));
  130.     
  131.     pb.ioIndex             = 0;
  132.     pb.ioFileCreator     = 'McPL';
  133.     pb.ioNamePtr         = file->name;
  134.     switch (err = PBDTGetAPPLSync(&pb))    {
  135.     case noErr:
  136.         file->vRefNum     = vRefNum;
  137.         file->parID     = pb.ioAPPLParID;
  138.     
  139.         return noErr;
  140.     case fnfErr:
  141.         return afpItemNotFound;                        /* Bug in PBDTGetAPPL            */
  142.     default:
  143.         return err;
  144.     }
  145. }
  146.  
  147. OSErr LaunchIt(FSSpecPtr fileSpec, ProcessSerialNumber * psn )
  148. {
  149.     OSErr                     err;
  150.     LaunchParamBlockRec     pb;
  151.     
  152.     pb.launchBlockID             = extendedBlock;
  153.     pb.launchEPBLength         = extendedBlockLen;
  154.     pb.launchFileFlags         = launchNoFileFlags;
  155.     pb.launchControlFlags    = launchContinue + launchNoFileFlags;
  156.     pb.launchAppSpec             = fileSpec;
  157.     pb.launchAppParameters    = nil;
  158.     
  159.     FAILOSERR(LaunchApplication(&pb));
  160.  
  161.     *psn = pb.launchProcessSN;
  162.     
  163.     return noErr;
  164. }
  165.  
  166. /* Get the psn ofa copy of MacPerl. Launch one if necessary. Buy one. Steal one. */
  167. static OSErr LaunchMacPerl(ProcessSerialNumber *psn)
  168. {
  169.     OSErr     err;
  170.     short     vRefNum, sysVRefNum, index;
  171.     FSSpec     file;
  172.     Boolean     hasDesktopDB;
  173.     
  174.     /* See if ToolServer is already running:                    */
  175.     err    = MacPerlRunning(psn);
  176.     
  177.     if    (err != procNotFound)
  178.         return err;
  179.     
  180.     /* Not running, try to launch it */
  181.     
  182.     FAILOSERR(GetSysVolume(&sysVRefNum));
  183.     
  184.     vRefNum = sysVRefNum;
  185.     
  186.     for (index = 0; !err; err = GetIndVolume(++index,&vRefNum)) {
  187.         if (!index || vRefNum != sysVRefNum) {
  188.             if (err = VolHasDesktopDB(vRefNum,&hasDesktopDB))
  189.                 return err;
  190.                 
  191.             if (hasDesktopDB)    
  192.                 switch (err = FindAppOnVolume(vRefNum, &file))    {
  193.                 case noErr:
  194.                     return LaunchIt(&file, psn);
  195.                 case afpItemNotFound:
  196.                     break;
  197.                 default:
  198.                     return err;
  199.                 }
  200.         }
  201.     }
  202.     
  203.     switch (err) {
  204.     case nsvErr:
  205.     case afpItemNotFound:
  206.         return fnfErr;
  207.     default:
  208.         return err;
  209.     }
  210. }
  211.  
  212. void WhoAmI(FSSpec * me)
  213. {
  214.     FCBPBRec        fcb;
  215.     
  216.     fcb.ioNamePtr    =    me->name;
  217.     fcb.ioRefNum    =    CurResFile();
  218.     fcb.ioFCBIndx    =    0;
  219.     
  220.     PBGetFCBInfoSync(&fcb);
  221.     
  222.     me->vRefNum    =    fcb.ioFCBVRefNum;
  223.     me->parID    =    fcb.ioFCBParID;
  224. }
  225.  
  226. pascal OSErr Yo(const AppleEvent *message, AppleEvent *reply, long refcon)
  227. {
  228.     OSErr                        err;
  229.     AppleEvent                doscript;
  230.     ProcessSerialNumber    perl;
  231.     AEAddressDesc            perladdr;
  232.     AEDescList                args;
  233.     AEDescList                incoming;
  234.     AliasHandle                alias;
  235.     AEDesc                    arg;
  236.     AEKeyword                kw;
  237.     Boolean                    doDebug = true;
  238.     
  239.     gQuitting = true;
  240.  
  241.     WaitNextEvent(0, &gLastEvent, 0, nil);
  242.     
  243.     switch (err = LaunchMacPerl(&perl)) {
  244.     case noErr:
  245.         break;
  246.     case fnfErr:
  247.         ParamText(
  248.             (StringPtr) "\pFailed to launch MacPerl. Either you don't have MacPerl "
  249.             "or your desktop needs to be rebuilt.", (StringPtr) "\p", "\p", "\p");
  250.         Alert(4096, nil);
  251.         
  252.         return err;
  253.     default:
  254.         ParamText(
  255.             (StringPtr) "\pFailed to launch MacPerl (possibly because of "
  256.             "a memory problem).", (StringPtr) "\p", "\p", "\p");
  257.         Alert(4096, nil);
  258.         
  259.         return err;
  260.     }
  261.     
  262.     FAILOSERR(SetFrontProcess(&perl));
  263.     
  264.     FAILOSERR(
  265.         AECreateDesc(
  266.             typeProcessSerialNumber,
  267.             (Ptr)&perl,
  268.             sizeof(ProcessSerialNumber),
  269.             &perladdr));
  270.     
  271.     if (refcon && (gLastEvent.modifiers & optionKey))
  272.         FAILOSERR(
  273.             AECreateAppleEvent(
  274.                 'McPL', kAEOpenDocuments, &perladdr, 
  275.                 kAutoGenerateReturnID, kAnyTransactionID, 
  276.                 &doscript));
  277.     else {
  278.         FAILOSERR(
  279.             AECreateAppleEvent(
  280.                 kAEMiscStandards, kAEDoScript, &perladdr, 
  281.                 kAutoGenerateReturnID, kAnyTransactionID, 
  282.                 &doscript));
  283.         if (gLastEvent.modifiers & controlKey)
  284.             FAILOSERR(AEPutParamPtr(&doscript, 'DEBG', typeBoolean, (Ptr) &doDebug, 1));
  285.     }
  286.     
  287.     FAILOSERR(AECreateList(nil,0,false,&args));
  288.     FAILOSERR(NewAlias(nil,&gMySelf,&alias));
  289.     
  290.     HLock((Handle) alias);
  291.     FAILOSERR(AEPutPtr(&args, 0, typeAlias, (Ptr) *alias, GetHandleSize((Handle) alias)));
  292.     DisposHandle((Handle) alias);
  293.     
  294.     if (!AEGetParamDesc(message, keyDirectObject, typeAEList, &incoming)) {
  295.         short    i = 1;
  296.         
  297.         while (!AEGetNthDesc(&incoming, i++, typeWildCard, &kw, &arg)) {
  298.             FAILOSERR(AEPutDesc(&args, 0, &arg));
  299.             AEDisposeDesc(&arg);
  300.         }
  301.         
  302.         AEDisposeDesc(&incoming);
  303.     }
  304.     
  305.     FAILOSERR(AEPutParamDesc(&doscript, keyDirectObject, &args));
  306.     FAILOSERR(
  307.         AESend(
  308.             &doscript, reply,
  309.             kAENoReply+kAEAlwaysInteract,
  310.             kAENormalPriority, kAEDefaultTimeout,
  311.             nil, nil));
  312.     
  313.     return noErr;
  314. }
  315.  
  316. pascal void MainEvent(void)
  317. {
  318.     if (WaitNextEvent(everyEvent, &gLastEvent, 60, nil))
  319.         switch (gLastEvent.what) {
  320.         case kHighLevelEvent:
  321.             AEProcessAppleEvent(&gLastEvent);
  322.             break;
  323.         }
  324. }
  325.  
  326. void main()
  327. {
  328.     InitGraf(&qd.thePort);
  329.     InitFonts();
  330.     FlushEvents(everyEvent, 0);
  331.     InitWindows();
  332.     InitMenus();
  333.     TEInit();
  334.     InitDialogs(nil);
  335.     InitCursor();
  336.  
  337.     gQuitting          = false;
  338.  
  339.     /*check environment checks to see if we are running 7.0*/
  340.     if (!CheckEnvironment()) {
  341.         SetCursor(&qd.arrow);
  342.         /*pose the only 7.0 alert*/
  343.         ParamText(
  344.             (StringPtr) "\pMacPerl droplets need at least System 7.0 to run "
  345.             "(you may run me from the \"MacPerl Runtime\" "
  346.             "application, however).", (StringPtr) "\p", "\p", "\p");
  347.         Alert(4096, nil);
  348.         
  349.         ExitToShell();
  350.     }
  351.  
  352.     /* We will not go native anytime soon */
  353.     
  354.     AEInstallEventHandler( kCoreEventClass, kAEOpenApplication, (AEEventHandlerUPP)Yo, 1, false) ;
  355.     AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments,   (AEEventHandlerUPP)Yo, 0, false) ;
  356.  
  357.     WhoAmI(&gMySelf);
  358.     
  359.     while (!gQuitting)
  360.         MainEvent();
  361. }
  362.  
  363. void RemoveConsole()
  364. {
  365. }
  366.